#include "main.h"
#include "NUC_communicate.h"
#include "robot_total_mode_task.h"
#include "struct_typedef.h"
#include "detect_task.h"
#include "OLED.h"
#include "cmsis_os.h"
#include "string.h"
#include "bsp_usart.h"
#include "referee.h"   
#include "protocol.h"
#include "robot_config.h"

//***************任务相关宏定义***************************//
#define ROBOT_NUC_TASK_INIT_TIME 1000  // 1000ms初始化
#define ROBOT_NUC_TASK_TIME 100  // 100ms执行一次

//***************全局变量*******************************//
extern UART_HandleTypeDef huart1;
extern DMA_HandleTypeDef hdma_usart1_rx;
static uint8_t nucinfo_rx_buf[2][NUCINFO_RX_BUF_NUM]; //防止DMA传输越界
static remote_control_t remote_control; //裁判系统图传链路
uint16_t cmd_id = 0;
uint8_t index = sizeof(frame_header_struct_t);
#ifdef USE_USART
static uint8_t gimbalreadmark = NUC_DATA_NOT_AVAILABLE;  //数据使用标志，值为0表明数据不可用（已使用过），值为1表明数据可用（被接收后尚未被使用）
static uint8_t shootreadmark = NUC_DATA_NOT_AVAILABLE;
static fromNUC_t nuc_ctrl; 
static toNUC_t toNUCData; 

#endif

void NUC_com_init(uint8_t *rx1_buf, uint8_t *rx2_buf, uint16_t dma_buf_num)
{
    //enable the DMA transfer for the receiver request
    //使能DMA串口接收
    SET_BIT(huart1.Instance->CR3, USART_CR3_DMAR);

    //enalbe idle interrupt
    //使能空闲中断
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

    //disable DMA
    //失效DMA
    __HAL_DMA_DISABLE(&hdma_usart1_rx);
    while(hdma_usart1_rx.Instance->CR & DMA_SxCR_EN)
    {
        __HAL_DMA_DISABLE(&hdma_usart1_rx);
    }

    hdma_usart1_rx.Instance->PAR = (uint32_t) & (USART1->DR);
    //memory buffer 1
    //内存缓冲区1
    hdma_usart1_rx.Instance->M0AR = (uint32_t)(rx1_buf);
    //memory buffer 2
    //内存缓冲区2
    hdma_usart1_rx.Instance->M1AR = (uint32_t)(rx2_buf);
    //data length
    //数据长度
    hdma_usart1_rx.Instance->NDTR = dma_buf_num;
    //enable double memory buffer
    //使能双缓冲区
    SET_BIT(hdma_usart1_rx.Instance->CR, DMA_SxCR_DBM);

    //enable DMA
    //使能DMA
    __HAL_DMA_ENABLE(&hdma_usart1_rx);

}

// 提供高层次封装
void nuc_control_init(void)
{
    NUC_com_init(nucinfo_rx_buf[0], nucinfo_rx_buf[1], NUCINFO_RX_BUF_NUM);
}

//串口中断
void USART1_IRQHandler(void)
{
    #ifdef LED_USART
    // aRGB_led_show(0xFFFF0000);
    #endif
    if(huart1.Instance->SR & UART_FLAG_RXNE)//接收到数据//接受中断
    {
        __HAL_UART_CLEAR_PEFLAG(&huart1);
    }
    else if(USART1->SR & UART_FLAG_IDLE)//空闲中断
    {
       static uint16_t this_time_rx_len = 0;

        __HAL_UART_CLEAR_PEFLAG(&huart1);

        if ((hdma_usart1_rx.Instance->CR & DMA_SxCR_CT) == RESET)
        {
            /* Current memory buffer used is Memory 0 */
    
            //disable DMA
            //失效DMA
            __HAL_DMA_DISABLE(&hdma_usart1_rx);

            //get receive data length, length = set_data_length - remain_length
            //获取接收数据长度,长度 = 设定长度 - 剩余长度
            this_time_rx_len = NUCINFO_RX_BUF_NUM- hdma_usart1_rx.Instance->NDTR;

            //reset set_data_lenght
            //重新设定数据长度
            hdma_usart1_rx.Instance->NDTR = NUCINFO_RX_BUF_NUM;

            //set memory buffer 1
            //设定缓冲??1
            hdma_usart1_rx.Instance->CR |= DMA_SxCR_CT;
            
            //enable DMA
            //使能DMA
            __HAL_DMA_ENABLE(&hdma_usart1_rx);
            cmd_id = 0;
            index = sizeof(frame_header_struct_t);
            memcpy(&cmd_id, nucinfo_rx_buf[0] + index, sizeof(uint16_t));
            index += sizeof(uint16_t);
            switch (cmd_id){
                case GRAPHIC_LINK_REMOTE_CONTROL_DATA_CMD_ID:
                {
                    memcpy(&remote_control, nucinfo_rx_buf[0] + index, sizeof(remote_control_t));
                    #ifdef LED_USART
                    aRGB_led_show(0xFF00FF00);
                    #endif
                }
                default:
                {
                    #ifdef LED_USART
                    // aRGB_led_show(0xFF0000FF);
                    #endif
                    break;
                }
            }
        }
        else
        {
            /* Current memory buffer used is Memory 1 */
            //disable DMA
            //失效DMA
            __HAL_DMA_DISABLE(&hdma_usart1_rx);

            //get receive data length, lengh = set_data_length - remain_length
            //获取接收数据长度,长度 = 设定长度 - 剩余长度
            this_time_rx_len = NUCINFO_RX_BUF_NUM - hdma_usart1_rx.Instance->NDTR;

            //reset set_data_lenght
            //重新设定数据长度
            hdma_usart1_rx.Instance->NDTR = NUCINFO_RX_BUF_NUM;

            //set memory buffer 
            //设定缓冲
            DMA2_Stream5->CR &= ~(DMA_SxCR_CT);
            
            //enable DMA
            //使能DMA
            __HAL_DMA_ENABLE(&hdma_usart1_rx);

            cmd_id = 0;
            index = sizeof(frame_header_struct_t);
            memcpy(&cmd_id, nucinfo_rx_buf[1] + index, sizeof(uint16_t));
            index += sizeof(uint16_t);
            switch (cmd_id){
                case GRAPHIC_LINK_REMOTE_CONTROL_DATA_CMD_ID:
                {
                    memcpy(&remote_control, nucinfo_rx_buf[1] + index, sizeof(remote_control_t));
                    detect_hook(REFEREE_CONTROL_TOE);
                }
                default:
                {
                    break;
                }
            }
        }
    }
}

#ifdef USE_USART
// 提供实时更新的NUC命令对应的数据指针
const fromNUC_t *get_nuc_control_point(void)
{
    return (const fromNUC_t*)&nuc_ctrl;
}


//数据解析
static void sbus_to_nucCtrl(volatile const uint8_t *sbus_buf, fromNUC_t *nuc_ctrl)
{
    if (sbus_buf == NULL || nuc_ctrl == NULL)
    {
        return;
    }
    (*nuc_ctrl)=(*((fromNUC_t*)sbus_buf));
}

//标记数据的接收状态
//云台
void gimbal_set_read_mark(void)
{
    gimbalreadmark = NUC_DATA_AVAILABLE;   //数据刚刚被接收，尚未使用
}

void gimbal_clear_read_mark(void)
{
    gimbalreadmark = NUC_DATA_NOT_AVAILABLE;
}

int gimbal_NUC_is_available(void)
{
    return (gimbalreadmark == NUC_DATA_AVAILABLE);
}
//发射
void shoot_set_read_mark(void)
{
    shootreadmark = NUC_DATA_AVAILABLE;   //数据刚刚被接收，尚未使用
}

void shoot_clear_read_mark(void)
{
    shootreadmark = NUC_DATA_NOT_AVAILABLE;
}

int shoot_NUC_is_available(void)
{
    return (shootreadmark == NUC_DATA_AVAILABLE);
}

// 检验NUC数据是否出错，
static int8_t verifiy_pass(void)
{
    uint8_t i;
    uint8_t sum = 0;
    uint8_t * data = (uint8_t *) &nuc_ctrl;
    for(i=1;i<sizeof(fromNUC_t)-2;i++)
        sum += data[i];
    if(nuc_ctrl.checksum == sum)
        return 1;
    else
        return 0;
}

void send_to_nuc(toNUC_t * data)
{
    static uint8_t usart_tx_buf[sizeof(toNUC_t)];
    memcpy(usart_tx_buf, (uint8_t*)data, sizeof(toNUC_t));
    usart1_tx_dma_enable(usart_tx_buf, sizeof(toNUC_t));
}


void to_nuc_send_task(void const *pvParameters)
{
    osDelay(ROBOT_NUC_TASK_INIT_TIME);
    #ifdef USE_CUSTOM_UI
    graphic_init();
    #endif
    while(1)
    {
        #ifdef TEST_USART
        send_to_nuc(&nuc_ctrl);
        #else
        // get_toNUCData(&toNUCData);
        // send_to_nuc(&toNUCData);
        #endif
        #ifdef USE_CUSTOM_UI
        graphic_data_update();
        #endif
        osDelay(ROBOT_NUC_TASK_TIME);
    }
}

int found_armor(void)
{
    if(toe_is_error(MINI_PC_TOE))
        return 0;
    if(nuc_ctrl.shoot == 1)
        return 1;
    else
        return 0;
}

int found_armorUp(void)
{
    if(toe_is_error(MINI_PC_TOE))
        return 0;
    if(nuc_ctrl.shootUp == 1)
        return 1;
    else
        return 0;
}

#endif

const remote_control_t* get_usart_remote_control_p(void){
    return &remote_control;
}

